package lumis.portal.group;

import lumis.portal.PortalException;
import lumis.portal.UnexpectedException;
import lumis.portal.cache.ICloneableCacheEntry;
import lumis.portal.stability.StableMinor;
import lumis.util.XmlUtil;

import java.io.OutputStream;

import org.w3c.dom.Node;

/**
 * Contains the information about a group principal in the portal.
 * 
 * @stereotype entity
 * 
 * @since 4.0.0
 * @version $Revision: 13082 $ $Date: 2011-05-27 16:03:12 -0300 (Fri, 27 May 2011) $
 */
@StableMinor(version = "6.0", sinceVersion = "4.0")
public class GroupConfig implements ICloneableCacheEntry
{
    public static final String GROUP_ALL_USERS_ID = "00000000C00000000000000000000001";
    public static final String GROUP_REGISTERED_USERS_ID = "00000000C00000000000000000000002";
    public static final String GROUP_ADMINISTRATORS_ID = "00000000C00000000000000000000003";
    public static final String GROUP_DEVELOPERS_ID = "00000000C00000000000000000000004";
    public static final String GROUP_PUBLISHERS_ID = "00000000C00000000000000000000005";
    public static final int GROUP_TYPE_STANDARD = 0;
    public static final int GROUP_TYPE_FRAMEWORK_IMPLIED_GROUPS = 1;
    public static final int GROUP_TYPE_FRAMEWORK = 2;
    
    
    private String id = null;
    private String alias = null;
    private String name = null;
    private String description = null;
    private int type = 0;
	private String accessControlListId = null;
	private String channelId = null;
	private String origin = null;
	private String groupTypeId = GroupType.GROUP_TYPE_STANDARD_ID;

	public String getOrigin()
	{
		return origin;
	}

	public void setOrigin(String origin)
	{
		this.origin = origin;
	}

	public String getAlias()
    {
        return alias;
    }

    public void setAlias(String alias)
    {
        this.alias = alias;
    }

    public String getDescription()
    {
        return description;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    public String getId()
    {
        return id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getType()
    {
        return type;
    }

    public void setType(int type)
    {
        this.type = type;
    }

	public String getAccessControlListId()
	{
		return accessControlListId;
	}

	public void setAccessControlListId(String accessControlListId)
	{
		this.accessControlListId = accessControlListId;
	}
	
	public String getChannelId()
	{
		return channelId;
	}

	public void setChannelId(String channel)
	{
		// just compare id instead of using GroupType.isCustom for optimization
		if (channel != null && !GroupType.GROUP_TYPE_STANDARD_ID.equals(getGroupTypeId()))
			throw new IllegalStateException("Cannot set channel on group of custom group type.");
		this.channelId = channel;
	}
	
	public String getGroupTypeId()
	{
		return groupTypeId;
	}

	public void setGroupTypeId(String groupTypeId)
	{
		// just compare id instead of using GroupType.isCustom for optimization
		if (getChannelId() != null && !GroupType.GROUP_TYPE_STANDARD_ID.equals(groupTypeId))
			throw new IllegalStateException("Cannot set group type on a local group.");
		this.groupTypeId = groupTypeId;
	}

	public boolean hasImpliedMembers()
	{
		return this.getId().equals(GROUP_ALL_USERS_ID) || this.getId().equals(GROUP_REGISTERED_USERS_ID);
	}
	
	public GroupConfig clone() throws CloneNotSupportedException
	{
		return (GroupConfig)super.clone();
	}
	
	public void serialize(GroupConfig groupConfig, OutputStream outputStream) throws PortalException
	{
		StringBuilder stream = new StringBuilder(500);
		
		stream.append("<group id=\""+getId()+"\">");
		stream.append("<channelId>"+getChannelId()+"</channelId>");
		stream.append("<aclId>"+getAccessControlListId()+"</aclId>");
		stream.append("<type>"+getType()+"</type>");
		
		String groupAlias = getAlias();
		if (getChannelId() != null && groupAlias != null)
		{
			// remove local group prefix from alias
			int separatorIndex = groupAlias.indexOf('.');
			groupAlias = groupAlias.substring(separatorIndex+1);
		}
		stream.append("<alias>" + XmlUtil.encodeXml(groupAlias) + "</alias>");
		
		stream.append("<name>" + XmlUtil.encodeXml(getName()) + "</name>");
		stream.append("<description>" + XmlUtil.encodeXml(getDescription()) + "</description>");
		stream.append("</group>");
	
		try
		{
			outputStream.write(stream.toString().getBytes("UTF-8"));
		}
		catch(Exception e)
		{
			throw new UnexpectedException(e);
		}
	}
	
	public void deserialize(Node groupNode) throws PortalException
	{
		try
		{
			setId(XmlUtil.readAttributeString("id", groupNode));
			setChannelId(XmlUtil.readNodeString("channelId", groupNode));
			setAccessControlListId(XmlUtil.readNodeString("aclId", groupNode, "").equals("") ? null : XmlUtil.readNodeString("aclId", groupNode));
			setType(Integer.parseInt(XmlUtil.readNodeString("type", groupNode, "0")));
			setAlias(XmlUtil.readNodeString("alias", groupNode));
			setName(XmlUtil.readNodeString("name", groupNode));
			setDescription(XmlUtil.readNodeString("description", groupNode));
		}
		catch(PortalException e)
		{
			throw e;
		}
		catch(Exception e)
		{
			throw new UnexpectedException(e);
		}
	}
}